package ae.pcfc.etks.online.web.controller.nonclient.company.register;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javassist.bytecode.DuplicateMemberException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.WebUtils;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WFProcessType;
import ae.pcfc.etks.online.common.delegate.AttachmentTypeDelegate;
import ae.pcfc.etks.online.common.delegate.NonClientCompanyRegisterDelegate;
import ae.pcfc.etks.online.common.delegate.UtilityDelegate;
import ae.pcfc.etks.online.common.vo.AttachmentTypeVO;
import ae.pcfc.etks.online.common.vo.CityVO;
import ae.pcfc.etks.online.common.vo.ClientCategoryVO;
import ae.pcfc.etks.online.common.vo.ClientRoleVO;
import ae.pcfc.etks.online.common.vo.CountryVO;
import ae.pcfc.etks.online.common.vo.LabelVO;
import ae.pcfc.etks.online.common.vo.LicIssueAuthVO;
import ae.pcfc.etks.online.common.vo.LicTypeVO;
import ae.pcfc.etks.online.common.vo.NonClientCompanyVO;
import ae.pcfc.etks.online.common.vo.UploadDocumentVO;
import ae.pcfc.etks.online.web.ConstantsAdmin;
import ae.pcfc.etks.online.web.PageType;
import ae.pcfc.etks.online.web.ViewPath;
import ae.pcfc.etks.online.web.ViewUtils;
import ae.pcfc.etks.online.web.common.Constants;
import ae.pcfc.etks.online.web.controller.BaseController;
import ae.pcfc.etks.online.web.model.NonClientCompanyRegistrationLicenseInfo;
import ae.pcfc.etks.online.web.util.SecurityUtils;

/**
 * Controller that handles all {@link Company}-related requests, i.e.: all
 * requests for /company/register/nonclient/
 * 
 * @author Neha Chauhan
 */
@Controller
@RequestMapping(ViewPath.COMPANY_REGISTRATION_NON_CLIENT)
public class NonClientCompanyController extends BaseController {

	private NonClientCompanyRegisterDelegate nonClientCompanyRegisterDelegate;
	private AttachmentTypeDelegate attachmentTypeDelegate;

	@Resource(name = "attachmentTypeDelegate")
	public void setAttachmentTypeDelegate(
			AttachmentTypeDelegate attachmentTypeDelegate) {
		this.attachmentTypeDelegate = attachmentTypeDelegate;
	}

	@Resource(name = "nonClientCompanyRegisterDelegate")
	public void setRegistrationDelegate(
			NonClientCompanyRegisterDelegate nonClientCompanyRegisterDelegate) {
		this.nonClientCompanyRegisterDelegate = nonClientCompanyRegisterDelegate;
	}

	private UtilityDelegate utilityDelegate;

	@Resource(name = "utilityDelegate")
	public void setUtilityDelegate(UtilityDelegate utilityDelegate) {
		this.utilityDelegate = utilityDelegate;
	}

	private Map<String, String> propertyConstants;

	@Resource(name = "propertyConstants")
	public void setPropertyConstants(Map<String, String> propertyConstants) {
		this.propertyConstants = propertyConstants;
	}

	@ModelAttribute(ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY)
	public NonClientCompanyRegistrationLicenseInfo populateRegisterNonClientCompanyLicenseInfoModel(
			HttpServletRequest request,
			@RequestParam(value = "id", required = false) String id) {

		return new NonClientCompanyRegistrationLicenseInfo();
	}

	@ModelAttribute(ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_CLIENT_ROLES_LIST_REQUEST_MODEL_KEY)
	public List<LabelVO> populateRegisterNonClientCompanyClientRolesList() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();
		LabelVO labelVO;
		List<ClientRoleVO> clientRoleVOs = utilityDelegate.getClientRoleList(
				Constants.COMPANY, true);

		for (ClientRoleVO roleVO : clientRoleVOs) {

			labelVO = getMapper().map(roleVO, LabelVO.class);
			labelList.add(labelVO);

		}

		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.CLIENT_CATEGORY_LIST_REQUEST_MODEL_KEY)
	public List<LabelVO> populateClientCategory() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();
		LabelVO labelVO = new LabelVO();

		labelList.add(labelVO);

		List<ClientCategoryVO> clientCategoryVOs = this.nonClientCompanyRegisterDelegate
				.getClientCategory(Constants.COMPANY);

		for (ClientCategoryVO categoryVO : clientCategoryVOs) {

			labelVO = getMapper().map(
					categoryVO, LabelVO.class);
			labelList.add(labelVO);
		}

		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_CLIENT_LICISSUEAUTHORITY_LIST_REQUEST_MODEL_KEY)
	public List<LabelVO> populateRegisterNonClientCompanyClientLicIssueAuth() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();

		LabelVO labelVO;
		List<LicIssueAuthVO> issueAuthVOs = utilityDelegate.getLicIssuingAuth();

		for (LicIssueAuthVO authVO : issueAuthVOs) {
			labelVO = getMapper().map(authVO,
					LabelVO.class);
			labelList.add(labelVO);

		}
		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_CLIENT_LICTYPE_LIST_REQUEST_MODEL_KEY)
	public List<LabelVO> populateRegisterNonClientCompanyClientLicTypeList() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();

		LabelVO labelVO;
		List<LicTypeVO> lictypeVOs = utilityDelegate.getLicType();

		for (LicTypeVO lictypeVO : lictypeVOs) {
			labelVO = getMapper().map(
					lictypeVO, LabelVO.class);
			labelList.add(labelVO);

		}

		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.COUNTRY_LIST_REQUEST_MODEL_KEY)
	public List<LabelVO> populateRegisterNonClientCompanyCountryEngList(
			Locale locale) {

		List<LabelVO> labelList = new ArrayList<LabelVO>();
		LabelVO labelVO = new LabelVO();

		labelList.add(labelVO);

		List<CountryVO> countryVOs = utilityDelegate.getCountryList(locale
				.toString());

		for (CountryVO countryVO : countryVOs) {
			labelVO = getMapper().map(
					countryVO, LabelVO.class);
			labelList.add(labelVO);

		}

		return labelList;
	}

	@RequestMapping(value = "/city", method = RequestMethod.GET)
	@ResponseBody
	public List<LabelVO> getCity(
			HttpServletRequest request,
			@RequestParam(value = "contryCode", required = true) String countryCode,
			Locale locale) {

		List<LabelVO> labelList = new ArrayList<LabelVO>();
		List<CityVO> cityVOs = utilityDelegate.getCityListByCountryCode(
				countryCode, locale.toString());

		LabelVO labelVO;

		labelVO = new LabelVO();
		labelList.add(labelVO);

		for (CityVO cityVO : cityVOs) {
			labelVO = getMapper().map(cityVO,
					LabelVO.class);
			labelList.add(labelVO);
		}

		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.NON_CLIENT_REGISTRATION_UPLOADDOCUMENT_TYPE_MODEL_KEY)
	public List<LabelVO> populateRegisterNonClientCompanyUploadDocumentType() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();
		LabelVO labelVO;
		String strAttachmentTypeUser = ConstantsAdmin.PROCESS_CODE_NON_CLIENT_COMPANY_REGISTRATION;
		List<AttachmentTypeVO> attachmentTypeVOs = attachmentTypeDelegate
				.getAttachmentType(strAttachmentTypeUser);

		for (AttachmentTypeVO attachmentTypeVO : attachmentTypeVOs) {
			labelVO = getMapper().map(
					attachmentTypeVO, LabelVO.class);
			labelList.add(labelVO);

		}
		return labelList;
	}

	/**
	 * Custom handler for displaying the form, i.e.: GET requests for
	 * /nonclient/company/register/licenseinfo/form.jsp
	 * 
	 * @see #form(HttpServletRequest,SessionStatus,NonClientCompanyRegistrationLicenseInfo,
	 *      BindingResult)
	 * @see WEB-INF/jsp/nonclient/company/register/licenseinfo/form.jsp
	 */
	@RequestMapping(value = "/form.htm", method = RequestMethod.GET)
	public void form(
			@ModelAttribute(value = ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) NonClientCompanyRegistrationLicenseInfo command) {

	}

	@RequestMapping(params = { "Upload" }, method = RequestMethod.POST, value = "/form.htm")
	public String uploadForm(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) @Valid NonClientCompanyRegistrationLicenseInfo nonClientCompanyRegistrationLicenseInfo,
			BindingResult errors, Model model) throws Exception {

		boolean isUpload = WebUtils.hasSubmitParameter(request,
				ConstantsAdmin.UPLOAD_BUTTON);

		try {

			if (isUpload) {
				if (errors.hasErrors()) {
					return ViewUtils.DEFAULT_VIEW;
				} else {

					if (uploadDocuments(request, errors, status,
							nonClientCompanyRegistrationLicenseInfo)) {
						request.setAttribute(ConstantsAdmin.SUCCESS_PARAM,
								nonClientCompanyRegistrationLicenseInfo
										.getStrUploadDocumentType());
						return ViewUtils.DEFAULT_VIEW;

					} else {
						request.setAttribute(ConstantsAdmin.ERROR_PARAM,
								ConstantsAdmin.ERROR_PARAM);
						String[] messageArgs = new String[] { getMessageSource()
								.getMessage("label.company.uploaddocuments",
										null,
										RequestContextUtils.getLocale(request)) };
						errors.reject("error.file.not.selected", messageArgs,
								null);
					}

				}
			}

		} catch (DuplicateMemberException dme) {
			request.setAttribute(ConstantsAdmin.ERROR_PARAM,
					ConstantsAdmin.ERROR_PARAM);
			String[] messageArgs = new String[] { getMessageSource().getMessage(
					"label.company.uploaddocuments", null,
					RequestContextUtils.getLocale(request)) };

			errors.reject("error.repeat", messageArgs, null);
		}

		catch (Exception e) {

			e.printStackTrace();
		}

		return ViewUtils.DEFAULT_VIEW;
	}

	public boolean uploadDocuments(
			HttpServletRequest request,
			BindingResult errors,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) @Valid NonClientCompanyRegistrationLicenseInfo nonClientCompanyRegistrationLicenseInfo)
			throws Exception {
		boolean uploaded = false;

		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		MultiValueMap<String, MultipartFile> files = multipartRequest
				.getMultiFileMap();

		// String strFinalVersion = "";
		// String documentType =
		// nonClientCompanyRegistrationLicenseInfo.getStrUploadDocumentType();

		if (files != null) {

			@SuppressWarnings("rawtypes")
			Iterator iter = files.keySet().iterator();

			while (iter.hasNext()) {
				String str = (String) iter.next();
				List<MultipartFile> fileList = files.get(str);

				for (MultipartFile mpf : fileList) {
					if (!(fileList.get(0)).isEmpty()) {
						String tempFileName = "" + System.currentTimeMillis();
						String fileExtension = FilenameUtils
								.getExtension(StringUtils.trim(mpf
										.getOriginalFilename()));

						String companyFolderPath = propertyConstants
								.get(ConstantsAdmin.UPLOAD_COMPANY_FILES_PATH_KEY);
						String tempFolderPath = propertyConstants
								.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);

						File uploadedFile = new File(tempFolderPath
								+ tempFileName + "." + fileExtension);
						FileOutputStream fos = new FileOutputStream(
								uploadedFile);
						// strFinalVersion =
						// StringUtils.trimAllWhitespace(mpf.getOriginalFilename());
						fos.write(mpf.getBytes());
						fos.close();
						uploaded = true;

						UploadDocumentVO documentVO = new UploadDocumentVO();

						documentVO.setStrName(FilenameUtils.getName(mpf
								.getOriginalFilename()));
						documentVO.setURL(companyFolderPath
								+ nonClientCompanyRegistrationLicenseInfo
										.getStrCompNameEng()
								+ tempFileName
								+"."+fileExtension);//uploaded file name companyName+tempFileName+extension
						documentVO
								.setStrUploadDocumentType(nonClientCompanyRegistrationLicenseInfo
										.getStrUploadDocumentType());
						documentVO.setStrTempFileName(tempFileName + "."
								+ fileExtension);
						documentVO.setStrExtension(fileExtension);

						List<UploadDocumentVO> arrDocumentVOs;

						if (nonClientCompanyRegistrationLicenseInfo
								.getArrDocumentVOs() == null) {
							arrDocumentVOs = new ArrayList<UploadDocumentVO>();
						} else
							arrDocumentVOs = nonClientCompanyRegistrationLicenseInfo
									.getArrDocumentVOs();

						for (UploadDocumentVO uploadDocumentVO : arrDocumentVOs) {
							if (uploadDocumentVO.getStrUploadDocumentType()
									.equals(documentVO
											.getStrUploadDocumentType())) {
								throw new DuplicateMemberException(
										"Cannnot Add again");
							}
						}

						arrDocumentVOs.add(documentVO);

						nonClientCompanyRegistrationLicenseInfo
								.setArrDocumentVOs(arrDocumentVOs);
					}
				}

			}
		}

		return uploaded;
	}

	@RequestMapping(params = { "next" }, method = RequestMethod.POST, value = "/form.htm")
	public NonClientCompanyRegistrationLicenseInfo populateRegisterNonClientCompanyPreviewSubmitModel(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) @Valid NonClientCompanyRegistrationLicenseInfo nonClientCompanyRegistrationLicenseInfo,
			BindingResult errors, Model model) {

		if (null != nonClientCompanyRegistrationLicenseInfo.getArrDocumentVOs()) {
			if (nonClientCompanyRegistrationLicenseInfo.getArrDocumentVOs()
					.size() < 2) {
				request.setAttribute(ConstantsAdmin.UPLOAD_PARAM,
						ConstantsAdmin.UPLOAD_PARAM);
				String[] messageArgs = new String[] { getMessageSource().getMessage(
						"label.company.uploaddocuments", null,
						RequestContextUtils.getLocale(request)) };
				errors.reject("error.file.uploadall", messageArgs, null);
			} else {
				request.setAttribute(ConstantsAdmin.PREVIEW_PARAM,
						ConstantsAdmin.PREVIEW_PARAM);
			}
		} else {
			request.setAttribute(ConstantsAdmin.UPLOAD_PARAM,
					ConstantsAdmin.UPLOAD_PARAM);
			String[] messageArgs = new String[] { getMessageSource().getMessage(
					"label.company.uploaddocuments", null,
					RequestContextUtils.getLocale(request)) };
			errors.reject("error.file.uploadall", messageArgs, null);
		}
		return nonClientCompanyRegistrationLicenseInfo;

	}

	/**
	 * Custom handler for displaying the form, i.e.:POST requests for
	 * /nonclient/company/register/licenseinfo/form.jsp
	 * 
	 * @see #form(NonClientCompanyRegistrationLicenseInfo)
	 * @see WEB-INF/jsp/nonclient/company/register/form.jsp
	 */

	@RequestMapping(method = RequestMethod.POST, value = "/form.htm")
	public String form(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY) @Valid NonClientCompanyRegistrationLicenseInfo nonClientCompanyRegistrationLicenseInfo,
			BindingResult errors) throws Exception {

		boolean isSubmit = WebUtils.hasSubmitParameter(request,
				ConstantsAdmin.SUBMIT_BUTTON);

		if (isSubmit) {
			if (errors.hasErrors()) {

				for (ObjectError error : errors.getAllErrors()) {
					System.out.println(error.getCode());
				}

				return ViewUtils.DEFAULT_VIEW;

			} else {
				for (UploadDocumentVO documentVO : nonClientCompanyRegistrationLicenseInfo
						.getArrDocumentVOs()) {
					String companyFolderPath = propertyConstants
							.get(ConstantsAdmin.UPLOAD_COMPANY_FILES_PATH_KEY);
					String tempFolderPath = propertyConstants
							.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);

					File uploadedFile = new File(tempFolderPath
							+ documentVO.getStrTempFileName());
					File uploadFile = new File(
							companyFolderPath
									+ nonClientCompanyRegistrationLicenseInfo
											.getStrCompNameEng()
									+ documentVO
											.getStrTempFileName()
									); //uploaded file name companyName+tempFileName

					FileUtils.copyFile(uploadedFile, uploadFile);
				}

				NonClientCompanyVO nonClientCompanyVO = new NonClientCompanyVO();
				getMapper().map(
						nonClientCompanyRegistrationLicenseInfo,
						nonClientCompanyVO);

				// TODO Mapper for Roles
				List<ClientRoleVO> list = new ArrayList<ClientRoleVO>();
				ClientRoleVO clientRoleVO;
				for (Integer role : nonClientCompanyRegistrationLicenseInfo
						.getiClientRole()) {

					clientRoleVO = new ClientRoleVO();
					clientRoleVO.setStrCrId(role.toString());

					list.add(clientRoleVO);
				}
				nonClientCompanyVO.setArrClientRole(list);

				// nonClientCompanyVO.setStrProcessCode(ConstantsAdmin.PROCESS_CODE_NON_CLIENT_COMPANY_REGISTRATION);
				nonClientCompanyVO
						.setProcessCode(WFProcessType.NON_CLIENT_COMPANY_REGISTRATION);
				nonClientCompanyVO.setApplicationDate(Calendar.getInstance()
						.getTime());
				nonClientCompanyVO
						.setStrWFinitatedBy(ConstantsAdmin.NON_CLIENT_COMPANY_WORK_FLOW_INITIATE);
				nonClientCompanyVO.setStrStatusEn(this.getMessageSource()
						.getMessage("msg.workflow.status.in.progress", null,
								Locale.ENGLISH));
				nonClientCompanyVO.setStrStatusAr(this.getMessageSource()
						.getMessage("msg.workflow.status.in.progress", null,
								new Locale(Constants.LOCALE_ARABIC)));

				nonClientCompanyVO.setStrWfStatus(ConstantsCommon.IN_PROGRESS);
				nonClientCompanyVO
						.setStrProcessStep(ConstantsAdmin.PROCESS_STEP_INITIATE_NON_CLIENT_COMPANY);
				nonClientCompanyVO.setStrClientType(Constants.COMPANY);

				String refNo = nonClientCompanyRegisterDelegate
						.registerNonClientCompany(nonClientCompanyVO);

				Map<String, String> paramMap = new HashMap<String, String>();
				paramMap.put(ConstantsAdmin.REFRENCE_NO, SecurityUtils.encryptQueryParam(refNo));

				status.setComplete();
				return ViewUtils.getRedirect(ViewPath.CONFIRMATION,
						PageType.SHOW, paramMap);

			}

		} else
			return ViewUtils.DEFAULT_VIEW;

	}
	/*
	 * @RequestMapping(params = { "delete" }, method = RequestMethod.POST, value
	 * = "/form.htm") public String deleteTempFile( HttpServletRequest request,
	 * 
	 * @RequestParam(value = "row", required = true) String fileIndex,
	 * 
	 * @ModelAttribute(value =
	 * ConstantsAdmin.NON_CLIENT_COMPANY_REGISTRATION_LICENSE_INFO_REQUEST_MODEL_KEY
	 * ) @Valid NonClientCompanyRegistrationLicenseInfo
	 * nonClientCompanyRegistrationLicenseInfo, BindingResult errors) throws
	 * IOException, NumberFormatException { boolean isDelete =
	 * WebUtils.hasSubmitParameter(request, ConstantsAdmin.DELETE_BUTTON); if
	 * (isDelete) { if (errors.hasErrors()) { return ViewUtils.DEFAULT_VIEW; }
	 * else { String tempFolderPath =
	 * propertyConstants.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);
	 * List<UploadDocumentVO> docs =
	 * nonClientCompanyRegistrationLicenseInfo.getArrDocumentVOs();
	 * UploadDocumentVO doc = docs.get(Integer.valueOf(fileIndex)); if(doc !=
	 * null){ File uploadedFile = new File(tempFolderPath + File.separator +
	 * doc.getStrTempFileName()); FileUtils.forceDelete(uploadedFile);
	 * docs.remove(Integer.parseInt(fileIndex));
	 * request.setAttribute(ConstantsAdmin.DELETE_PARAM,
	 * doc.getStrUploadDocumentType());
	 * request.setAttribute(ConstantsAdmin.SUCCESS_PARAM,
	 * doc.getStrUploadDocumentType()); }else{ String[] messageArgs = new
	 * String[] { getMessageSource().getMessage("error.delete.file", null,
	 * RequestContextUtils.getLocale(request))}; errors.reject(messageArgs[0],
	 * null); } return ViewUtils.DEFAULT_VIEW; } } return
	 * ViewUtils.DEFAULT_VIEW;
	 * 
	 * }
	 */
}
